#include "stdafx.h"
#include "BitmapClass.h"


CBitmapClass::CBitmapClass(void) : m_pTexture(nullptr), m_pVertexBuffer(nullptr), m_pIndexBuffer(nullptr), m_nVertexCount(-1), n_nIndexCount(-1), 
	m_nScreenWidth(-1), m_nScreenHeight(-1), m_nBitmapWidth(-1), m_nBitmapHeight(-1), m_nPreviousXPos(-1), m_nPreviousYPos(-1)
{
}


CBitmapClass::~CBitmapClass(void)
{
}

bool CBitmapClass::Initialize(ID3D11Device* pDevice, int nScreenWidth, int nScreenHeight, WCHAR* pwszFileName, int nBitmapWidth, int nBitmapHeight)
{
	bool bResult = false;

	m_nScreenWidth = nScreenWidth;
	m_nScreenHeight = nScreenHeight;
	m_nBitmapWidth = nBitmapWidth;
	m_nBitmapHeight = nBitmapHeight;

	m_nPreviousXPos = -1;
	m_nPreviousYPos = -1;

	bResult = InitializeBuffers(pDevice);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failes to initialize bitmap buffers");
		return false;
	}

	bResult = LoadTexture(pDevice, pwszFileName);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to load bitmap texture");
		return false;
	}

	return true;
}

void CBitmapClass::ShutDown()
{
	ReleaseTexture();
	ShutDownBuffers();
}

bool CBitmapClass::Render(ID3D11DeviceContext* pDeviceContext, int nXPos, int nYPos)
{
	bool bResult = false;

	bResult = UpdateBuffers(pDeviceContext, nXPos, nYPos);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to update bitmap buffers");
		return false;
	}

	RenderBuffers(pDeviceContext);

	return true;
}

int CBitmapClass::GetIndexCount()
{
	return n_nIndexCount;
}

ID3D11ShaderResourceView* CBitmapClass::GetTexture()
{
	return m_pTexture->GetTexture();
}

bool CBitmapClass::InitializeBuffers(ID3D11Device* pDevice)
{
	VertexType* pVertices = nullptr;
	unsigned long* pIndices = nullptr;
	D3D11_BUFFER_DESC stVertexBufferDesc;
	D3D11_BUFFER_DESC stIndexBufferDesc;
	D3D11_SUBRESOURCE_DATA stVertexData;
	D3D11_SUBRESOURCE_DATA stIndexData;
	HRESULT hResult;

	m_nVertexCount = 6;
	n_nIndexCount = m_nVertexCount;

	pVertices = new VertexType[m_nVertexCount];
	if(pVertices == nullptr)
	{
		DEBUG_OUTPUT("Failed to create the bitmap vertex type");
		return false;
	}

	pIndices = new unsigned long[n_nIndexCount];
	if(pIndices == nullptr)
	{
		DEBUG_OUTPUT("Failed to create the bitmap index type");
		return false;
	}

	memset(pVertices, 0, (sizeof(VertexType) * m_nVertexCount));

	for(int i = 0; i < n_nIndexCount; ++i)
	{
		pIndices[i] = i;
	}

	stVertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
	stVertexBufferDesc.ByteWidth = sizeof(VertexType) * m_nVertexCount;
	stVertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	stVertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	stVertexBufferDesc.MiscFlags = 0;
	stVertexBufferDesc.StructureByteStride = 0;

	stVertexData.pSysMem = pVertices;
	stVertexData.SysMemPitch = 0;
	stVertexData.SysMemSlicePitch = 0;

	hResult = pDevice->CreateBuffer(&stVertexBufferDesc, &stVertexData, &m_pVertexBuffer);
	if(FAILED(hResult))
	{
		DEBUG_OUTPUT("Failed to create bitmap vertex buffer");
		return false;
	}

	stIndexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	stIndexBufferDesc.ByteWidth = sizeof(unsigned long) * n_nIndexCount;
	stIndexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	stIndexBufferDesc.CPUAccessFlags = 0;
	stIndexBufferDesc.MiscFlags = 0;
	stIndexBufferDesc.StructureByteStride = 0;

	stIndexData.pSysMem = pIndices;
	stIndexData.SysMemPitch = 0;
	stIndexData.SysMemSlicePitch = 0;

	hResult = pDevice->CreateBuffer(&stIndexBufferDesc, &stIndexData, &m_pIndexBuffer);
	if(FAILED(hResult))
	{
		DEBUG_OUTPUT("Failed to create bitmap index buffer");
		return false;
	}

	delete[] pVertices;
	pVertices = nullptr;

	delete[] pIndices;
	pIndices = nullptr;

	return true;
}

void CBitmapClass::ShutDownBuffers()
{
	if(m_pIndexBuffer != nullptr)
	{
		m_pIndexBuffer->Release();
		m_pIndexBuffer = nullptr;
	}

	if(m_pVertexBuffer != nullptr)
	{
		m_pVertexBuffer->Release();
		m_pVertexBuffer = nullptr;
	}
}

bool CBitmapClass::UpdateBuffers(ID3D11DeviceContext* pDeviceContext, int nXPos, int nYPos)
{
	float fLeft = 0.0f;
	float fTop = 0.0f;
	float fRight = 0.0f;
	float fBottom = 0.0f;

	VertexType* pVertices = nullptr;
	VertexType* pVerticesPtr = nullptr;
	D3D11_MAPPED_SUBRESOURCE stMappedResource;
	HRESULT hResult;

	if((m_nPreviousXPos == nXPos) && (m_nPreviousYPos == nYPos))
	{
		return true;
	}

	m_nPreviousXPos = nXPos;
	m_nPreviousYPos = nYPos;

	fLeft = (float)((m_nScreenWidth / 2) * -1) + (float)nXPos;
	fRight = fLeft + (float)m_nBitmapWidth;
	fTop = (float)(m_nScreenHeight / 2) - (float)nYPos;
	fBottom = fTop - (float)m_nBitmapHeight;

	pVertices = new VertexType[m_nVertexCount];
	if(pVertices == nullptr)
	{
		DEBUG_OUTPUT("Failed to create bitmap vertex pointer");
		return false;
	}

	pVertices[0].d3dPosition = D3DXVECTOR3(fLeft, fTop, 0.0f); // Top Left
	pVertices[0].d3dTexture = D3DXVECTOR2(0.0f, 0.0f);

	pVertices[1].d3dPosition = D3DXVECTOR3(fRight, fBottom, 0.0f); // Bottom Right
	pVertices[1].d3dTexture = D3DXVECTOR2(1.0f, 1.0f);

	pVertices[2].d3dPosition = D3DXVECTOR3(fLeft, fBottom, 0.0f); // Bottom Left
	pVertices[2].d3dTexture = D3DXVECTOR2(0.0f, 1.0f);

	pVertices[3].d3dPosition = D3DXVECTOR3(fLeft, fTop, 0.0f); // Top Left
	pVertices[3].d3dTexture = D3DXVECTOR2(0.0f, 0.0f);

	pVertices[4].d3dPosition = D3DXVECTOR3(fRight, fTop, 0.0f); // Top Right
	pVertices[4].d3dTexture = D3DXVECTOR2(1.0f, 0.0f);

	pVertices[5].d3dPosition = D3DXVECTOR3(fRight, fBottom, 0.0f); // Bottom Right
	pVertices[5].d3dTexture = D3DXVECTOR2(1.0f, 1.0f);

	hResult = pDeviceContext->Map(m_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &stMappedResource);
	if(FAILED(hResult))
	{
		DEBUG_OUTPUT("Failed to map bitmap vertex buffer");
		return false;
	}

	pVerticesPtr = (VertexType*)stMappedResource.pData;

	memcpy(pVerticesPtr, (void*)pVertices, (sizeof(VertexType) * m_nVertexCount));
	
	pDeviceContext->Unmap(m_pVertexBuffer, 0);

	delete[] pVertices;
	pVertices = nullptr;

	return true;
}

void CBitmapClass::RenderBuffers(ID3D11DeviceContext* pDeviceContext)
{
	unsigned int nStride = sizeof(VertexType);
	unsigned int nOffset = 0;

	pDeviceContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &nStride, &nOffset);
	pDeviceContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
	pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

bool CBitmapClass::LoadTexture(ID3D11Device* pDevice, WCHAR* pwszFileName)
{
	bool bResult = false;

	m_pTexture = new CTextureClass();
	if(m_pTexture == nullptr)
	{
		DEBUG_OUTPUT("Failed to create bitmap texture pointer");
		return false;
	}

	bResult = m_pTexture->Initialize(pDevice, pwszFileName);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize bitmap texture pointer");
		return false;
	}

	return true;
}

void CBitmapClass::ReleaseTexture()
{
	if(m_pTexture != nullptr)
	{
		m_pTexture->ShutDown();
		delete m_pTexture;
		m_pTexture = nullptr;
	}
}